/*
 * Created by Jaren at 2022/2/21 13:57
 */
import 'dart:async';
import 'dart:io';
import 'package:inmotion_protocol/base/file/file_manager.dart';
import 'package:inmotion_protocol/base/protocol.dart';
import 'package:inmotion_protocol/lorin/constant.dart';
import 'package:inmotion_protocol/lorin/file/lorin_file_download_manager.dart';
import 'package:inmotion_protocol/lorin/file/lorin_file_manager.dart';
import 'package:inmotion_protocol/lorin/file/lorin_file_upload_manager.dart';
import 'package:inmotion_protocol/lorin/lorin_message.dart';
import 'package:inmotion_protocol/util/log.dart';

class AvatarFileManager {

    final Protocol<LorinMessage> _protocol;

    bool canceled = true;

    LorinFileDownloadManager? _fileDownloadManager;
    LorinFileUploadManager? _fileUploadManager;

    AvatarFileManager(this._protocol);

    void downloadConfig(LorinAvatarFileConfig config) {
        _fileDownloadManager = LorinFileDownloadManager(_protocol, config);
    }

    void uploadConfig(LorinAvatarFileConfig config) {
        _fileUploadManager = LorinFileUploadManager(_protocol, config);
    }

    Stream<Event> download() {
        canceled = false;

        StreamController<Event> streamController = StreamController();
        _fileDownloadManager!.start().listen((fileEvent) {
            LogUtils.d('AvatarFileManager|download, ${fileEvent.toString()}');
            switch (fileEvent.type) {
                case FileEvent.fileOpened:
                    break;
                case FileEvent.fileProgress:
                    streamController.add(FileTransferringEvent(fileEvent as FileProgressEvent));
                    break;
                case FileEvent.prepareFileChecking:
                    break;
                case FileEvent.fileChecked:
                    break;
                case FileEvent.fileClosed:
                    streamController.add(Event(Event.typeFileTransferFinished));
                    // 结束
                    streamController.close();
                    break;
            }
        }).onError((error) {
            if (error is CanceledError) {
                streamController.add(Event.byCanceled());
                // 结束
                streamController.close();
            }
            streamController.addError(error);
            // 结束
            streamController.close();
            throw error;
        });
        return streamController.stream;
    }

    Stream<Event> upload() {
        canceled = false;

        StreamController<Event> streamController = StreamController();
        _fileUploadManager!.start().listen((fileEvent) {
            LogUtils.d('AvatarFileManager|upload, ${fileEvent.toString()}');
            switch (fileEvent.type) {
                case FileEvent.fileOpened:
                    break;
                case FileEvent.fileProgress:
                    streamController.add(FileTransferringEvent(fileEvent as FileProgressEvent));
                    break;
                case FileEvent.prepareFileChecking:
                    break;
                case FileEvent.fileChecked:
                    break;
                case FileEvent.fileClosed:
                // 增加延时，保证设备端足够时间刷新图片
                    Future.delayed(const Duration(milliseconds: 1500), () {
                        streamController.add(Event(Event.typeFileTransferFinished));
                        // 结束
                        streamController.close();
                    });
                    break;
            }
        }).onError((error) {
            if (error is CanceledError) {
                streamController.add(Event.byCanceled());
                // 结束
                streamController.close();
            }
            streamController.addError(error);
            // 结束
            streamController.close();
            throw error;
        });
        return streamController.stream;
    }

    void cancel() {
        canceled = true;
        if (_fileDownloadManager != null) _fileDownloadManager!.interrupt();
        if (_fileUploadManager != null) _fileUploadManager!.interrupt();
    }
}

class Event {
    static const typeCanceled = 0;
    static const typeFileTransferring = 1;
    static const typeFileTransferFinished = 2;

    int type = -1;

    Event(this.type);

    Event.byCanceled() :this(typeCanceled);


    @override
    String toString() {
        return 'Event{type: $type}';
    }
}

class FileTransferringEvent extends Event {

    final FileProgressEvent _fileProgressEvent;

    FileTransferringEvent(this._fileProgressEvent) : super(Event.typeFileTransferring);

    /// 当前进度
    int progress() {
        return _fileProgressEvent.progress;
    }

    /// 总大小
    int total() {
        return _fileProgressEvent.total;
    }

    /// 平均速度
    int aveSpeed() {
        return _fileProgressEvent.aveSpeed;
    }

    /// 实时速度
    int rtSpeed() {
        return _fileProgressEvent.rtSpeed;
    }

    /// 已用时间
    int costSeconds() {
        return _fileProgressEvent.costSeconds;
    }

    /// 预计剩余时间
    int remainSeconds() {
        return _fileProgressEvent.remainSeconds;
    }

    @override
    String toString() {
        return 'FileTransferringEvent{_fileProgressEvent: $_fileProgressEvent}';
    }
}

class LorinAvatarFileConfig extends LorinFileManagerConfig {

    bool ignoreCache;

    LorinAvatarFileConfig(int target, int openType, String remoteFilename, File localFile, this.ignoreCache) : super(target, openType, remoteFilename, localFile);

    static LorinAvatarFileConfig create(String localFilePath,
        {int target = Constant.deviceEUCV12BLE, String remoteFilePath = 'user.jpg', int openFileTpe = IFileManager.openFileTypeRadWrite, bool ignoreCache = false}) {
        return LorinAvatarFileConfig(target, openFileTpe, remoteFilePath, File(localFilePath), ignoreCache);
    }
}
